package map.areaeffect;

import java.util.HashMap;

import loadsave.Memento;
import loadsave.loadsaveobject.Iterator;
import loadsave.loadsaveobject.LoadSaveMapComposite;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import map.GameWorld;
import map.Position;
import entity.Entity;
import factory.AEFactory;

public class EntityAEAssociation {
	
	private HashMap<Position, AreaEffect> areaEffects;
	private HashMap<Entity, AreaEffectApplier> appliers;
	
	public EntityAEAssociation() {
		
		this.areaEffects = new HashMap<Position, AreaEffect>();
		this.appliers = new HashMap<Entity, AreaEffectApplier>();
	}
	
	public AreaEffect getAreaEffect(Position position) {
		
		return areaEffects.get(position);
	}
	
	public void addAreaEffect(AreaEffect areaEffect, Position position) {
		
		areaEffects.put(position, areaEffect);
	}
	
	public void updateEntity(Entity entity, Position position) {
		
		AreaEffectApplier applier = null;
		
		//check to see whether the entity had an effect being applied to it
		//if it did, remove the applier
		if(appliers.containsKey(entity)) {
			
			applier = appliers.get(entity);
			applier.unschedule();
			appliers.remove(entity);
		}
		
		//if there is an area effect at the entity's new position,
		//create an applier and schedule it on the scheduler
		if(areaEffects.containsKey(position)) {
			
			AreaEffect areaEffect = areaEffects.get(position);
			applier = new AreaEffectApplier(areaEffect, entity);
			applier.schedule();
			appliers.put(entity, applier);
		}
	}
	
    public Memento getMemento() {
    	return new Memento() {

			@Override
			public LoadSaveObject getState() {
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("", "EntityAEAssociation");
				LoadSaveMapComposite lsmc = new LoadSaveMapComposite("areaEffects", "HashMap", "Position", "AreaEffect");
				for (Position p : areaEffects.keySet()) {
					lsmc.add(p.getMemento().getState(), areaEffects.get(p).getMemento().getState());
				}
				toReturn.add(lsmc.getName(), lsmc);
				lsmc = new LoadSaveMapComposite("appliers", "HashMap", "Entity", "AreaEffectApplier");
				for (Entity e : appliers.keySet()) {
					lsmc.add(e.getMemento().getState(), appliers.get(e).getMemento().getState());
				}
				toReturn.add(lsmc.getName(), lsmc);
				return toReturn;
			}

			@Override
			public void restoreState(LoadSaveObject lso) {
				areaEffects = new HashMap<Position, AreaEffect>();
				Iterator<LoadSaveObject> i = lso.get("areaEffects").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					Position p = new Position();
					p.getMemento().restoreState(i.getCurrKey());
					areaEffects.put(p, AEFactory.createAreaEffect(i.getCurrVal()));
				}
				appliers = new HashMap<Entity, AreaEffectApplier>();
				i = lso.get("appliers").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					AreaEffectApplier ap = new AreaEffectApplier();
					ap.getMemento().restoreState(i.getCurrVal());
					appliers.put(GameWorld.getInstance().getEntity(i.getCurrKey().get("name").getValue()), ap);
				}
			}
    		
    	};
    }
}
